import { createDecorator } from '../core/helpers'
import { computed  } from 'vue'

export interface ProvideOptions{
    name: string | symbol;
    ref?: boolean;
}

function create(params:ProvideOptions,target: any, propertyKey: string,descriptor?: PropertyDescriptor){
    createDecorator(function (ctx, key) {
        const options = ctx.options
        if(!options.provide){
            const provideFun = function(this:any){
                const result = Object.create(null);

                for (const [key, params] of provideFun.values) {
                    //默认响应式设置
                    if(params.ref === false){
                        result[params.name] = this[key]
                    }else{
                        result[params.name] = computed(() => this[key])
                    }

                }

                for (const [key, params] of provideFun.funs) {
                    result[params.name] = (...args:any)=>{
                        return this[key](...args)
                    }
                }
                return result
            }
            provideFun.values = new Map<string,ProvideOptions>()
            provideFun.funs = new Map<string,ProvideOptions>();
            options.provide = provideFun
        }
        const provide:any = options.provide

        if(descriptor?.value){
            provide.funs.set(key,params)
        }else if(descriptor?.get){
            provide.values.set(key,params)
        }else{
            provide.values.set(key,params)
        }
    })(target, propertyKey);
}

export function Provide(params:string):any;
export function Provide(params:symbol):any;
export function Provide(params:ProvideOptions):any;
export function Provide(target: any, propertyKey: string):void;
export function Provide(target: any, propertyKey: string,descriptor: PropertyDescriptor):void;
export function Provide(target: any, propertyKey="",descriptor?: PropertyDescriptor):void | any{
    if(propertyKey){
        create({name:propertyKey},target,propertyKey,descriptor)
    }else{
        const targetType = typeof target
        const params:ProvideOptions =  targetType === 'string' || targetType === 'symbol' ? {name:target} : target as ProvideOptions
        return function (target: any, propertyKey: string,descriptor?: PropertyDescriptor) {
            create(params,target,propertyKey,descriptor)
        };

    }
}
